package org.learn.simple.file.server.handlers;

import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelOutboundHandlerAdapter;
import io.netty.channel.ChannelPromise;
import io.netty.handler.codec.http.*;
import org.learn.simple.file.server.parse.HtmlParser;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.lang.reflect.ParameterizedType;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.Collection;
import java.util.List;

/**
 * @author <a href="mailto:675464934@qq.com">Terrdi</a>
 * @date 2021/12/19
 * @since 1.8
 **/
public class ShowDirectoryHandler extends ChannelOutboundHandlerAdapter {
    @Override
    public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws Exception {
        Class clazz = msg.getClass();
        if (List.class.isAssignableFrom(clazz)) {
            HtmlParser htmlParser = new HtmlParser("template.html");
            htmlParser.addAll((Collection<String>) msg);
            ByteBuf byteBuf = Unpooled.copiedBuffer(htmlParser.toString(), StandardCharsets.UTF_8);
            HttpResponse httpResponse = new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.OK,
                    byteBuf);
            httpResponse.headers().set(HttpHeaderNames.CONTENT_TYPE, "text/html")
                    .set(HttpHeaderNames.CONTENT_LENGTH, byteBuf.readableBytes());

            ctx.writeAndFlush(httpResponse);
        } else if (File.class.isAssignableFrom(clazz)) {
            ByteBuf result = this.resolve((File) msg);
            HttpResponse httpResponse = new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.OK,
                    result);
            httpResponse.headers().set(HttpHeaderNames.CONTENT_TYPE, HttpHeaderValues.MULTIPART_FORM_DATA)
                    .set(HttpHeaderNames.CONTENT_LENGTH, result.readableBytes())
                    .set(HttpHeaderNames.CONTENT_DISPOSITION, HttpHeaderValues.ATTACHMENT + ";filename=" +
                            URLEncoder.encode(((File) msg).getName(), "UTF-8"));

            ctx.writeAndFlush(httpResponse);
        } else {
            super.write(ctx, msg, promise);
        }
    }

    public ByteBuf resolve(File file) throws IOException {
        ByteBuf result;
        try (FileInputStream fis = new FileInputStream(file)) {
            result = Unpooled.buffer(fis.available());
            byte[] buf = new byte[1024];
            int cnt = -1;
            do {
                if (cnt > 0) {
                    result.writeBytes(buf, 0, cnt);
                }
                cnt = fis.read(buf);
            } while (cnt >= 0);
        }

        return result;
    }
}
